/*!
 *  \file       StaircaseSignalGenerator.cpp
 *  \brief      Implementazione della classe \c StaircaseSignalGenerator
 *  \author     Davide Scola <S2299453@studenti.unige.it>
 *  \author	Minetti Alberto <S3064777@studenti.unige.it>
 *  \version    1.0
 *
 */
#include <vector>
#include <sstream>
#include <utility>
#include "ISignalGenerator.hpp"
#include "StaircaseSignalGenerator.hpp"

using namespace std;


/*!
 *  \brief      Parsing di un intervallo
 *
 *  Questo metodo parsa una stringa contenente un intervallo chiuso i cui estremi
 *  sono separati dal carattere '-'; i whitespace vengono ignorati
 *
 *  \param[in]	input	stringa che identifica l'intervallo
 *  \param[out]	range	estremi dell'intervallo
 */
template< typename tType > bool
StaircaseSignalGenerator< tType >::parseInterval( const char *input, std::pair< tType, tType > &range )
{
  char sep;
  bool retValue = true;
  istringstream sstream( input );
  
  if ((sstream >> (&range)->first >> sep >> (&range)->second >> ws) && sstream.eof() && sep == '-') {
    if( (&range)->first > (&range)->second ) {
      swap( (&range)->first, (&range)->second );
    }
  }
  
  else {
    retValue = false;
  }
  
  sstream.clear();
  return retValue;
}

/*!
 *  \brief      Controlla se una variabile e' contenuta in un range
 *
 *  \param[in]	value	valore da controllare
 *  \param[in]	range	estremi dell'intervallo
 */
template< typename tType > inline bool
StaircaseSignalGenerator< tType >::isInRange( tType value, std::pair< tType, tType > &range )
{
  return value >= (&range)->first && value <= (&range)->second;
}


/*!
 *  \brief	Costruttore della classe \c StaircaseSignalGenerator
 *
 *  \see	StaircaseSignalGenerator< tType >::StaircaseSignalGenerator( StaircaseSignalGenerator< tType > const& other )
 */
template< class tType >
StaircaseSignalGenerator< tType >::StaircaseSignalGenerator( int argc, char *argv[] )
    : currPoint_( 0 )
{
  pair< tType, tType > range;
  
  for( int i = 0; i < argc; ++i )
  {
    if( this->parseInterval( argv[i], range ) )
      this->intervals_.push_back( range );
  }
}

/*!
 *  \brief      Costruttore di copia della classe \c StaircaseSignalGenerator
 *  \param[in]	other	generatore da copiare
 *
 *  \see	StaircaseSignalGenerator< tType >::StaircaseSignalGenerator( int argc, char *argv[] )
 */
template< class tType >
StaircaseSignalGenerator< tType >::StaircaseSignalGenerator( StaircaseSignalGenerator< tType > const& other )
    : currPoint_( (&other)->currPoint_ ),
      intervals_( (&other)->intervals_ )
{
}


/*!
 *  \brief      Operatore di assegnazione della classe \c StaircaseSignalGenerator
 */
template < typename tType > StaircaseSignalGenerator< tType >&
StaircaseSignalGenerator< tType >::operator=( const StaircaseSignalGenerator& other )
{
   if (this == &other) {
       return *this;
   }
   
   this->currPoint_ = (&other)->currPoint_;
   this->intervals_ = (&other)->intervals_;
   return *this;
}


/*!
 *  \brief      Generatore del segnale
 *  \return	ritorna un segnale costanti a tratti
 */
template< class tType > tType
StaircaseSignalGenerator< tType >::operator() ( void )
{
  tType retValue = tType( 0 );
  
  for( unsigned long int i = 0; i < this->intervals_.size(); ++i )
  {
    if( this->isInRange( this->currPoint_, this->intervals_[i] ) ) {
      retValue = tType( 1 );
      break;
    }
  }
  
  this->currPoint_ += 1;
  return retValue;
}
